#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Rendering;
#endif

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;

namespace CNGraphi.U6URP
{
    /// <summary>
    /// 颜色转换器
    /// <para>作者：CN.Graphi</para>
    /// </summary>
    [VolumeComponentMenu("G Post-processing/Color Variator")]
    public class ColorVariator : GPostProcess
    {
        #region 参数
        public FloatParameter brightness = new FloatParameter(1.0f);
        public FloatParameter saturation = new FloatParameter(1.0f);
        public FloatParameter contrast = new FloatParameter(1.0f);
        public ClampedIntParameter hue = new ClampedIntParameter(0, -180, 180);
        public BoolParameter negation = new BoolParameter(false, false);
        public BoolParameter negationRChannel = new BoolParameter(true, false);
        public BoolParameter negationGChannel = new BoolParameter(true, false);
        public BoolParameter negationBChannel = new BoolParameter(true, false);
        public ColorParameter colorFilter = new ColorParameter(Color.white, true);
        #endregion


        public override bool IsActive() => mMaterial != null &&
                                            (
                                                brightness.value != 1.0f ||
                                                saturation.value != 1.0f ||
                                                contrast.value != 1.0f ||
                                                hue.value != 0 ||
                                                negation.value ||
                                                colorFilter.value != Color.white
                                            );

       

        internal override void OnRender(CommandBuffer cmd, PostProcessPassData passData, TextureHandle src, TextureHandle dst)
        {
            if (mMaterial == null) return;

            // brightness
            CoreUtils.SetKeyword(mMaterial, "_USE_BRIGHTNESS", brightness.value != 1.0f);
            mMaterial.SetFloat("_Brightness", brightness.value);

            // saturation
            CoreUtils.SetKeyword(mMaterial, "_USE_SATURATION", saturation.value != 1.0f);
            mMaterial.SetFloat("_Saturation", saturation.value);

            // contrast
            CoreUtils.SetKeyword(mMaterial, "_USE_CONTRAST", contrast.value != 1.0f);
            mMaterial.SetFloat("_Contrast", contrast.value);

            // hue
            CoreUtils.SetKeyword(mMaterial, "_USE_HUE", hue.value != 0);
            mMaterial.SetFloat("_Hue", hue.value);

            // negation
            CoreUtils.SetKeyword(mMaterial, "_USE_NEGATION", negation.value);
            mMaterial.SetVector("_NegationChannel", new Vector3(
                negationRChannel.value ? 1 : 0,
                negationGChannel.value ? 1 : 0,
                negationBChannel.value ? 1 : 0
                ));

            CoreUtils.SetKeyword(mMaterial, "_USE_COLORFILTER", colorFilter.value != Color.white);
            mMaterial.SetColor("_ColorFilter", colorFilter.value);

            Draw(cmd, src, dst, 0);
        }

        internal override void OnTextureCreate(RenderGraph renderGraph, ContextContainer frameData)
        {
        }

        internal override void OnTextureUseCommit(IUnsafeRenderGraphBuilder builder)
        {
        }

        protected override void OnDispose()
        {
        }
    }


#if UNITY_EDITOR
    [CustomEditor(typeof(ColorVariator))]
    internal class ColorVariatorEditor : VolumeComponentEditor
    {
        SerializedDataParameter brightness;
        SerializedDataParameter saturation;
        SerializedDataParameter contrast;
        SerializedDataParameter hue;
        SerializedDataParameter negation;
        SerializedDataParameter negationRChannel;
        SerializedDataParameter negationGChannel;
        SerializedDataParameter negationBChannel;
        SerializedDataParameter renderShader;
        SerializedDataParameter colorFilter;
        

        public override void OnEnable()
        {
            base.OnEnable();

            PropertyFetcher<ColorVariator> o = new PropertyFetcher<ColorVariator>(serializedObject);
            brightness = Unpack(o.Find(x => x.brightness));
            saturation = Unpack(o.Find(x => x.saturation));
            contrast = Unpack(o.Find(x => x.contrast));
            hue = Unpack(o.Find(x => x.hue));
            negation = Unpack(o.Find(x => x.negation));
            negationRChannel = Unpack(o.Find(x => x.negationRChannel));
            negationGChannel = Unpack(o.Find(x => x.negationGChannel));
            negationBChannel = Unpack(o.Find(x => x.negationBChannel));
            renderShader = Unpack(o.Find(x => x.RenderShader));
            colorFilter = Unpack(o.Find(x => x.colorFilter));
        }


        public override void OnInspectorGUI()
        {
            EditorGUILayout.Space(5);
            PropertyField(colorFilter);
            PropertyField(brightness);
            PropertyField(saturation);
            PropertyField(contrast);
            PropertyField(hue);
            PropertyField(negation);
            if (negation.overrideState.boolValue && negation.value.boolValue)
            {
                EditorGUI.indentLevel++;
                PropertyField(negationRChannel, new GUIContent("R Channel"));
                PropertyField(negationGChannel, new GUIContent("G Channel"));
                PropertyField(negationBChannel, new GUIContent("B Channel"));
                EditorGUI.indentLevel--;
            }
            PropertyField(renderShader);
        }
    }
#endif
}